#!/usr/bin/env bash

include "objectv5.sh"
include "test.sh"

ObjectV5::DefineClass LineVisitor "
    --string=file
"

function LineVisitor::LineVisitor()
{
    local this="$1"; shift

    LineVisitor::file "$this" "$(mktemp "/tmp/LineVisitor.XXXXXXXX")"
}

function LineVisitor::~LineVisitor()
{
    local this="$1"; shift

    rm -f "$(LineVisitor::file "$this")"
}

function LineVisitor::AppendLine()
{
    local this="$1"; shift

    echo "$*" >> "$(LineVisitor::file "$this")"
}

function LineVisitor::ProcessOutput()
{
    local LineVisitor_this="$1"; shift
    local LineVisitor_on_process_output="$1"; shift

    local LineVisitor_result="$($LineVisitor_on_process_output < "$(LineVisitor::file "$LineVisitor_this")")"
    echo "$LineVisitor_result" > "$(LineVisitor::file "$LineVisitor_this")"
}

function LineVisitor::Visit()
{
    local LineVisitor_this="$1"; shift
    local LineVisitor_on_process_line="$1"; shift

    local LineVisitor_line
    local LineVisitor_i=1
    while read LineVisitor_line; do
        $LineVisitor_on_process_line "$LineVisitor_line" "$((LineVisitor_i++))"
    done < "$(LineVisitor::file "$LineVisitor_this")"
}

function LineVisitor::Test1()
{
    local visitor
    LineVisitor visitor
    LineVisitor::AppendLine visitor "2 c d"
    LineVisitor::AppendLine visitor "1 a b"
    LineVisitor::AppendLine visitor "1 a b"

    function TestOnProcessOutput()
    {
        sort | uniq
    }
    LineVisitor::ProcessOutput visitor TestOnProcessOutput

    local line=""
    local linenum=""
    function TestOnProcessLine()
    {
        line+="$1"
        linenum+="$2"
    }

    LineVisitor::Visit visitor TestOnProcessLine
    test::var_should_be line "1 a b2 c d"
    test::var_should_be linenum "12"
}
test::register_test LineVisitor::Test1

function LineVisitor::Test2()
{
    local visitor
    LineVisitor visitor
    LineVisitor::AppendLine visitor "2 c d"
    LineVisitor::AppendLine visitor "1 a b"
    LineVisitor::AppendLine visitor "1 a b"

    LineVisitor::ProcessOutput visitor sort
    LineVisitor::ProcessOutput visitor uniq

    local line=""
    local linenum=""
    function TestOnProcessLine()
    {
        line+="$1"
        linenum+="$2"
    }

    LineVisitor::Visit visitor TestOnProcessLine
    test::var_should_be line "1 a b2 c d"
    test::var_should_be linenum "12"
}
test::register_test LineVisitor::Test2
